import { triplitClient } from "@main/triplit/client";
import type {
  McpServer,
  Thread,
  ThreadMcpServer,
  UpdateThreadMcpServerData,
} from "@shared/triplit/types";
import { injectable } from "inversify";

@injectable()
export class ThreadMcpServerDbService {
  // CRUD 基础操作
  async addMcpServerToThread(
    threadId: string,
    mcpServerId: string,
    options?: { enabled?: boolean; order?: number },
  ): Promise<ThreadMcpServer> {
    return await triplitClient.insert("threadMcpServers", {
      threadId,
      mcpServerId,
      enabled: options?.enabled ?? true,
      order: options?.order ?? 0,
    });
  }

  async removeMcpServerFromThread(
    threadId: string,
    mcpServerId: string,
  ): Promise<void> {
    const query = triplitClient
      .query("threadMcpServers")
      .Where("threadId", "=", threadId)
      .Where("mcpServerId", "=", mcpServerId);

    const associations = await triplitClient.fetch(query);

    for (const association of associations) {
      await triplitClient.delete("threadMcpServers", association.id);
    }
  }

  async updateThreadMcpServer(
    threadId: string,
    mcpServerId: string,
    updateData: UpdateThreadMcpServerData,
  ): Promise<void> {
    const query = triplitClient
      .query("threadMcpServers")
      .Where("threadId", "=", threadId)
      .Where("mcpServerId", "=", mcpServerId);

    const associations = await triplitClient.fetch(query);

    for (const association of associations) {
      await triplitClient.update(
        "threadMcpServers",
        association.id,
        (entity) => {
          Object.assign(entity, updateData, {
            updatedAt: new Date(),
          });
        },
      );
    }
  }

  // 查询操作
  async getMcpServersByThreadId(threadId: string): Promise<McpServer[]> {
    const query = triplitClient
      .query("threadMcpServers")
      .Where("threadId", "=", threadId)
      .Include("mcpServer")
      .Order("order", "ASC");

    const associations = await triplitClient.fetch(query);
    return associations
      .map((assoc) => assoc.mcpServer)
      .filter((server): server is McpServer => Boolean(server));
  }

  async getEnabledMcpServersByThreadId(threadId: string): Promise<McpServer[]> {
    const query = triplitClient
      .query("threadMcpServers")
      .Where("threadId", "=", threadId)
      .Where("enabled", "=", true)
      .Include("mcpServer")
      .Order("order", "ASC");

    const associations = await triplitClient.fetch(query);
    return associations
      .map((assoc) => assoc.mcpServer)
      .filter((server): server is McpServer => Boolean(server));
  }

  async getThreadMcpServersByThreadId(
    threadId: string,
  ): Promise<ThreadMcpServer[]> {
    const query = triplitClient
      .query("threadMcpServers")
      .Where("threadId", "=", threadId)
      .Order("order", "ASC");

    return await triplitClient.fetch(query);
  }

  async getEnabledThreadMcpServersByThreadId(
    threadId: string,
  ): Promise<ThreadMcpServer[]> {
    const query = triplitClient
      .query("threadMcpServers")
      .Where("threadId", "=", threadId)
      .Where("enabled", "=", true)
      .Order("order", "ASC");

    return await triplitClient.fetch(query);
  }

  async getThreadsByMcpServerId(mcpServerId: string): Promise<Thread[]> {
    const query = triplitClient
      .query("threadMcpServers")
      .Where("mcpServerId", "=", mcpServerId)
      .Include("thread");

    const associations = await triplitClient.fetch(query);
    return associations
      .map((assoc) => assoc.thread)
      .filter((thread): thread is Thread => Boolean(thread));
  }

  async isServerEnabledForThread(
    threadId: string,
    mcpServerId: string,
  ): Promise<boolean> {
    const query = triplitClient
      .query("threadMcpServers")
      .Where("threadId", "=", threadId)
      .Where("mcpServerId", "=", mcpServerId)
      .Where("enabled", "=", true);

    const associations = await triplitClient.fetch(query);
    return associations.length > 0;
  }

  // 批量操作
  async setThreadMcpServers(
    threadId: string,
    serverIds: string[],
  ): Promise<void> {
    // 先清除现有关联
    await this.clearThreadMcpServers(threadId);

    // 添加新关联
    for (let i = 0; i < serverIds.length; i++) {
      await triplitClient.insert("threadMcpServers", {
        threadId,
        mcpServerId: serverIds[i],
        enabled: true,
        order: i,
      });
    }
  }

  async clearThreadMcpServers(threadId: string): Promise<void> {
    const query = triplitClient
      .query("threadMcpServers")
      .Where("threadId", "=", threadId);

    const associations = await triplitClient.fetch(query);

    for (const association of associations) {
      await triplitClient.delete("threadMcpServers", association.id);
    }
  }

  async deleteAllAssociationsForServer(mcpServerId: string): Promise<void> {
    const query = triplitClient
      .query("threadMcpServers")
      .Where("mcpServerId", "=", mcpServerId);

    const associations = await triplitClient.fetch(query);

    for (const association of associations) {
      await triplitClient.delete("threadMcpServers", association.id);
    }
  }

  async reorderThreadMcpServers(
    threadId: string,
    serverOrders: Array<{ serverId: string; order: number }>,
  ): Promise<void> {
    for (const { serverId, order } of serverOrders) {
      const query = triplitClient
        .query("threadMcpServers")
        .Where("threadId", "=", threadId)
        .Where("mcpServerId", "=", serverId);

      const associations = await triplitClient.fetch(query);

      for (const association of associations) {
        await triplitClient.update(
          "threadMcpServers",
          association.id,
          (entity) => {
            entity.order = order;
            entity.updatedAt = new Date();
          },
        );
      }
    }
  }
}
